package com.remoter.filter.internal;

import java.lang.reflect.Method;

import com.remoter.basic.bean.support.ProviderModule;
import com.remoter.basic.bean.support.RemoterRequest;
import com.remoter.basic.bean.support.RemoterResponse;
import com.remoter.basic.configure.IConfiguration;
import com.remoter.basic.configure.support.AbstractConfiguration;
import com.remoter.basic.context.IContext;
import com.remoter.basic.task.ITaskFilter;
import com.remoter.basic.util.Final;
import com.remoter.basic.util.ObjectChain;
import com.remoter.basic.util.ServiceLoader;
import com.remoter.basic.util.ServiceLoader.MetaName;
import com.remoter.basic.util.StringUtil;

/**
 * @author			koko
 * @date 			2017-08-09 10:12:21
 * @description 	类功能说明
 */
@MetaName("rpc")
public class RemoterProcedureFilter implements ITaskFilter{
	
	private static IConfiguration configuration;
	private static IContext context;
	
	@Override
	public void execute(RemoterRequest remoterRequest, RemoterResponse remoterResponse,ObjectChain<ITaskFilter> chain) {
		if(null == configuration){
			synchronized(RemoterProcedureFilter.class){
				if(null == configuration){
					configuration = AbstractConfiguration.getConfiguration();
				}
			}
		}
		if(null == context){
			synchronized(RemoterProcedureFilter.class){
				if(null == context){
					context = ServiceLoader.getService(IContext.class,configuration.getOption(Final.O_VAL_CONTEXT));
				}
			}
		}
		
		try{
			String serviceClassString = remoterRequest.getType();
			String serviceBeanName = remoterRequest.getBean();
			String serviceMethodName = remoterRequest.getMethod();
			if(StringUtil.isBlank(serviceClassString) || StringUtil.isBlank(serviceBeanName) || StringUtil.isBlank(serviceMethodName)){
				remoterResponse.setException("service data error for bean["+serviceBeanName+"]: " + serviceClassString + "." + serviceMethodName);
				return;
			}
			Class<?>[] serviceParamTypes = remoterRequest.getParamType();
			Object[] serviceParamObjects = remoterRequest.getParamObject();
			Class<?> serviceClass = Class.forName(serviceClassString);
			
			ProviderModule module = context.getProviderModule(remoterRequest);
			if(null == module){
				remoterResponse.setException("service instance not found : " + serviceClassString);
				return;
			}
			Method method = serviceClass.getMethod(serviceMethodName,serviceParamTypes);
			if(null == method){
				remoterResponse.setException("method not found : " + serviceClassString + "." + serviceMethodName);
				return;
			}
			remoterResponse.setData(method.invoke(module.getInstance(),serviceParamObjects));
		}catch(Throwable e){
			e.printStackTrace();
			remoterResponse.setException(e.getMessage());
		}
	}
	
}